#include "hpcr_types.h"
#include "core/hpcr_list.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct data
{
    hpcr_list_node_t node;
    int age;
    char name[16];
};

typedef struct data data_t;

bool compare(hpcr_list_node_t *dst, hpcr_list_node_t *node)
{
    if (((data_t *)dst)->age <= ((data_t *)node)->age)
    {
        return true;
    }
    return false;
}

bool search(hpcr_list_node_t *dst, void *arg)
{
    if (((data_t *)dst)->age == *(int *)(arg))
    {
        return true;
    }
    return false;
}

data_t *new_instance(int age, char *name)
{
    data_t *instance = (data_t *)malloc(sizeof(data_t));
    instance->age = age;
    strcpy(instance->name, name);
    return instance;
}

void printList(hpcr_list_t *list)
{
    hpcr_list_node_t *item = list->head.next;
    printf("-------------List print start-------------\n");
    while (item->next != NUL)
    {
        data_t *tmp = (data_t *)item;
        printf("name=%s age=%d\n", tmp->name, tmp->age);
        item = item->next;
    }
    printf("--------------List print finish!------------\n");
    return;
}

void printListNode(hpcr_list_node_t *item)
{
    data_t *tmp = (data_t *)item;
    printf("name=%s age=%d\n", tmp->name, tmp->age);
    return;
}

int main()
{
    hpcr_list_node_t *item;
    data_t *tmp;

    data_t *data_li[5] = {
        new_instance(1, "son"),
        new_instance(60, "grandpa"),
        new_instance(50, "grandma"),
        new_instance(20, "mother"),
        new_instance(30, "father"),
    };

    hpcr_list_t list;
    hpcr_list_init(&list);

    for (int i = 0; i < 5; i++)
    {
        hpcr_list_insert_order(&list, (hpcr_list_node_t *)data_li[i], compare);
    }

    item = list.head.next;
    while (item->next != NUL)
    {
        data_t *tmp = (data_t *)item;
        printf("name=%s age=%d\n", tmp->name, tmp->age);
        item = item->next;
    }

    int findAge = 20;
    // test search
    hpcr_list_node_t *search_result = hpcr_list_find(&list, search, &findAge);

    if (search_result != NUL)
    {
        data_t *tmp = (data_t *)search_result;
        printf("search_result: %s %d\n", tmp->name, tmp->age);
    }

    // 测试push和pop
    printf("start test pop!\n");
    printf("original item order:\n");
    printList(&list);
    for (int i = 0; i < 10; i++)
    {
        item = hpcr_list_pop(&list);
        if (item == NUL)
        {
            printf("List is empty!");
            break;
        }
        printf("pop item: ");
        printListNode(item);
        printf("after pop list item order:\n");
        printList(&list);
    }

    // 测试两个push
    printf("*****************Test push************\n");
    hpcr_list_push(&list, data_li[0]);
    printList(&list);
    hpcr_list_push(&list, data_li[1]);
    printList(&list);

    printf("*****************Test append ****************\n");
    // 测试两个append
    hpcr_list_append(&list, data_li[2]);
    printList(&list);
    hpcr_list_append(&list, data_li[3]);
    printList(&list);

    printf("*****************Test remove****************\n");
    hpcr_list_remove(data_li[0]);
    printList(&list);

    printf("*****************Test size and empty****************\n");
    while (hpcr_list_pop(&list) != NUL)
    {
        printf("list size: %d\n", hpcr_list_size(&list));
        printf("list is empty ? %d\n", hpcr_list_empty(&list));
    }

    return 0;
}